Type LibraryLoaderXMLStrategy Extends LibraryLoaderStrategy

	Field progress:Float = -1
	Field status:String  = ""
	Field xmlFileName:String
	Field xsltFileName:String
	
	Method Load(loader:LibraryLoader)
		progress = 0
		status   = "Loading XSLT file."
		loader.NotifyObservers()
		xmlSubstituteEntitiesDefault(1)
		xmlDoValidityCheckingDefaultValue = 0
		xmlGetWarningsDefaultValue = 1
		xmlLineNumbersDefaultValue = 1
		xmlLoadExtDtdDefaultValue  = 0
		xmlParserDebugEntities     = 1
		xmlSaveNoEmptyTags         = 0		
		Local xml:String           = LoadString(xsltFileName)
		progress = 0.025
		status   = "Loading XML file."
		loader.NotifyObservers()
		Local xsltDoc:TxmlDoc      = TxmlDoc.parseDoc(xml)
		progress = 0.050
		status   = "Applying XSLT."
		loader.NotifyObservers()
		Local xslt:TxsltStylesheet = TxsltStylesheet.parseStylesheetDoc(xsltDoc)
		Local doc:TxmlDoc          = xslt.applyStylesheet(TxmlDoc.parseFile(xmlFileName))
		progress = 0.075
		status   = "Fetching tracks."
		loader.NotifyObservers()
		'doc.saveFormatFile("-", True)
		Local context:TxmlXPathContext
		Local result:TxmlXPathObject
		context = doc.newXPathContext()
		If context = Null Then
			Throw "Error in newXPathContext"
			Return
		End If
		result   = context.evalExpression("/tracks/track")
		progress = 0.1
		status   = "Inspecting tracks."
		loader.NotifyObservers()
		Local trackMap:Tmap = New Tmap		
		If result Then
			Local nodeList:TList = result.getNodeSet().getNodeList()
			Local inc:Float      = (65.0 / nodeList.Count()) * 0.01
			For Local node:TxmlNode = EachIn nodeList
				Local t:TrackInformation = New TrackInformation
				processTrackNode(t, node)
				progress:+inc
				If t.id Then
					trackMap.insert(String(t.id), t)
					status = "Adding track " + t.ToString()
					loader.addTrackInformation(t)
				Else
					status = "Skipping track " + t.ToString()
					loader.NotifyObservers()
				End If
			Next
			result.free()
		End If		
		progress = 0.75
		status   = "Fetching playlists."
		loader.NotifyObservers()
		result   = context.evalExpression("/playlists/playlist")
		progress = 0.80
		status   = "Inspecting playlists."
		loader.NotifyObservers()
		If result Then
			Local nodeList:TList = result.getNodeSet().getNodeList()
			Local inc:Float      = (20.0 / nodeList.Count()) * 0.01
			For Local node:TxmlNode = EachIn nodeList
				Local p:Playlist = New Playlist
				processPlaylistNode(trackMap, p, node)
				progress:+inc
				If p.id And p.items.count() > 0 Then
					status = "Adding playlist " + p.ToString()
					loader.addPlaylist(p)
				Else
					status = "Skipping playlist " + p.ToString()
					loader.NotifyObservers()
				End If
			Next
			result.free()
		End If	
		trackMap.clear()
		progress = 1.0
		status   = "Done."
		loader.NotifyObservers()
		context.free()
		doc.free()			
	End Method

	Method getProgress:Float()
		Return progress
	End Method
	
	Method getStatusMessage:String()
		Return status
	End Method
	
	Method processTrackNode(t:TrackInformation, trackNode:TxmlNode)
		Local childList:TList = trackNode.getChildren()
		Local value:String
		For Local childNode:TxmlNode = EachIn childList
			value = childNode.getText().Trim()
			Select childNode.getName().ToLower()
				Case "track_id"
					t.id          = value.toInt()
				Case "name"
					t.name        = value
				Case "artist"
					t.artist      = value
				Case "album"
					t.album       = value
				Case "genre"
					t.genre       = value
				Case "disc_number"
					t.discNumber  = value.toInt()
				Case "disc_count"
					t.discCount   = value.toInt()
				Case "track_number"
					t.trackNumber = value.toInt()
				Case "track_count"
					t.trackCount  = value.toInt()
				Case "year"
					t.year        = value.toInt()
				Case "location"
					t.trackUrl    = value
				Case "track_url"
					t.trackUrl    = value
				Case "image_url"
					t.imageUrl    = value
			End Select
		Next
	End Method
	
	Method processPlaylistNode(trackMap:TMap, p:Playlist, playlistNode:TxmlNode)
		Local childList:TList = playlistNode.getChildren()
		Local value:String
		For Local childNode:TxmlNode = EachIn childList
			value = childNode.getText().Trim()
			Select childNode.getName().ToLower()
				Case "playlist_id"
					p.id          = value.toInt()
				Case "name"
					p.name        = value
				Case "track_id"
					Local t:TrackInformation = TrackInformation(trackMap.ValueForKey(value))
					If t Then
						p.items.AddLast(t)
					End If
			End Select
		Next
	End Method

End Type

